package com.niiwoo.civet.account.service.local.refund.newRefund;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dangdang.ddframe.rdb.sharding.api.HintManager;
import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.niiwoo.civet.account.constant.RedissonLockConstant;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.BatchTransOrder;
import com.niiwoo.civet.account.dao.entity.ProTransactionOrder;
import com.niiwoo.civet.account.dao.entity.WithholdOrder;
import com.niiwoo.civet.account.dao.mapper.AccountBaseMapperExt;
import com.niiwoo.civet.account.dao.mapper.BatchTransOrderMapperExt;
import com.niiwoo.civet.account.dao.mapper.ProTransactionOrderMapperExt;
import com.niiwoo.civet.account.dao.mapper.WithholdOrderMapperExt;
import com.niiwoo.civet.account.dto.common.AccountBatchTransOrderDTO;
import com.niiwoo.civet.account.dto.request.UpdateRechargeRequestDTO;
import com.niiwoo.civet.account.dto.response.UpdateRechargeResponseDTO;
import com.niiwoo.civet.account.enums.OrderEndTypeEnum;
import com.niiwoo.civet.account.enums.RefundStatusEnum;
import com.niiwoo.civet.trade.enums.BatchRefundTypeEnum;
import com.niiwoo.civet.trade.enums.RepayStatusEnum;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.*;
import com.niiwoo.tripod.lanmao.properties.LanMaoProperties;
import com.niiwoo.tripod.lanmao.request.QueryTransactionRequest;
import com.niiwoo.tripod.lanmao.response.LanMaoResponse;
import com.niiwoo.tripod.lanmao.response.QueryPretransactionResponse;
import com.niiwoo.tripod.lanmao.response.QueryRechargeResponse;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.FastDateFormat;
import org.joda.time.DateTime;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * Created by bincun on 2018/03/05.
 * 还款流程补单
 */
@Slf4j
@Service
public class AccountRefundProcessAutoLocalService {

    @Autowired
    private AccountRefundHandleLocalService accountRefundHandleLocalService;
    @Autowired
    private RefundQueryLocalService refundQueryLocalService;
    @Autowired
    private BatchTransOrderMapperExt batchTransOrderMapperExt;
    @Autowired
    private WithholdOrderMapperExt withholdOrderMapperExt;
    @Autowired
    private LanMaoDirectService lanMaoDirectService;
    @Autowired
    private LanMaoSequence lanMaoSequence;
    @Autowired
    private LanMaoProperties lanMaoProperties;
    @Autowired
    private RefundBaseLocalService refundBaseLocalService;
    @Autowired
    private ProTransactionOrderMapperExt proTransactionOrderMapperExt;
    @Autowired
    private LanmaoRefundLocalService lanmaoRefundLocalService;
    @Autowired
    private RefundMsgLocalService refundMsgLocalService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private AccountBaseMapperExt accountBaseMapperExt;

    public String getGuaranteeUserId(){
        return ""+lanMaoProperties.getNiiWooAccount().getGuaranteeUserId();
    }




    /**
     * 还款补单流程
     */
    public void completedRefundJob() throws ExecutionException, InterruptedException {
//        log.info("还款补单流程completedRefundJob");
//        String startTime = FastDateFormat.getInstance("YYYY-MM-dd HH:mm:ss").format(new DateTime(new Date()).plusHours(-96).toDate());
//        String endTime = FastDateFormat.getInstance("YYYY-MM-dd HH:mm:ss").format(new DateTime(new Date()).plusMinutes(-15).toDate());
//
//        List<Long> batchTransOrderIds = batchTransOrderMapperExt.selectBatchTransOrderIdByStatus(startTime,endTime);
//
//        log.info("本次还款补单处理订单数量{}个，BatchOrderIds={}",batchTransOrderIds.size(), JSON.toJSON(batchTransOrderIds));
//        for (Long batchId : batchTransOrderIds){
//            //列表查询锁定查询范围，每一个订单都重新查询一次，拿到最新订单状态再作处理
//            if (!HintManagerHolder.isMasterRouteOnly()) {
//                HintManagerHolder.clear();
//                HintManager hintManager = HintManager.getInstance();
//                hintManager.setMasterRouteOnly();
//            }
//            BatchTransOrder batchOrder = batchTransOrderMapperExt.selectByPrimaryKey(batchId);
//            if (batchOrder == null){
//                log.info("还款订单不存在,batchId={}",batchId);
//                continue;
//            }
//            //处理完成，直接跳过
//            if (RefundStatusEnum.HANDLING.getValue() != batchOrder.getStatus()){
//                log.info("订单已处理完毕,batchRequestNO={}",batchOrder.getBatchRequestNo());
//                continue;
//            }
//            //是否需要向下一个流程处理
//            boolean handleFlag;
//            if (!batchOrder.getBatchRefundType().equals(BatchRefundTypeEnum.GUARANTEE.getValue())
//                    && !batchOrder.getBatchRefundType().equals(BatchRefundTypeEnum.NEED_GUARANTEE_REFUND.getValue())){
//                log.info("还款(代扣)补单开始,batchRequestNo={}",batchOrder.getBatchRequestNo());
//                try {
//                    handleFlag = this.handWithholdOrderStatus(batchOrder);
//                }catch (Exception e){
//                    log.error("还款(代扣)补单开始,batchRequestNo={}，异常",batchOrder.getBatchRequestNo());
//                    log.error("还款(代扣)异常,",e);
//                    handleFlag = false;
//                }
//            }else {
//                handleFlag = true;
//            }
//            if (handleFlag){
//                log.info("还款预处理补单开始,batchRequestNo={}",batchOrder.getBatchRequestNo());
//                try {
//                    this.handPreTransactionStatus(batchOrder);
//                }catch (Exception e){
//                    log.error("还款(预处理)异常,batchRequestNo={}，异常",batchOrder.getBatchRequestNo());
//                    log.error("还款(预处理)异常,",e);
//                }
//            }
//
//        }


    }

    /**
     * 1如代扣订单状态为处理中，则主动查询存管状态，存管失败-》还款失败；存管成功—>余额+，代扣成功，还款失败；存管处理中-》不处理，跳过
     * 2如代扣订单状态为失败，则更新还款订单为失败
     * 3如代扣订单为成功，不处理，中止
     * @return  是否可以执行下一步
     */
    private boolean handWithholdOrderStatus(BatchTransOrder batchOrder) throws ExecutionException, InterruptedException {
        if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
        WithholdOrder withholdOrder = withholdOrderMapperExt.selectOrderByBatchRequestNo(batchOrder.getBatchRequestNo());
        return this.handForWithhold(batchOrder,withholdOrder);
    }

    /**
     * 处理还款订单已失败的代扣订单
     */
    public void handBatchOrderFailWithhold(){
        try {
            String startTime = FastDateFormat.getInstance("YYYY-MM-dd HH:mm:ss").format(new DateTime(new Date()).plusHours(-360).toDate());
            String endTime = FastDateFormat.getInstance("YYYY-MM-dd HH:mm:ss").format(new DateTime(new Date()).plusMinutes(-32).toDate());
            List<WithholdOrder> failOrders = withholdOrderMapperExt.selectWithholdOrderByFailStatus(startTime,endTime);
            if (!CollectionUtils.isEmpty(failOrders)){
                for (WithholdOrder withholdOrder:failOrders) {
                    if (withholdOrder != null) {
                        BatchTransOrder batchTransOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(withholdOrder.getBatchRequestNo());
                        if (batchTransOrder != null && batchTransOrder.getStatus() == 3) {
                            try {
                                this.handForWithhold(batchTransOrder, withholdOrder);
                            } catch (ExecutionException | InterruptedException e) {
                                log.info("处理异常代扣订单异常,withholdRequestNo{}", withholdOrder.getRequestNo(), e);
                            }
                            //只处理失败的
                        } else {
                            //非失败状态-不处理
                            log.info("非失败状态-不处理BatchRequestNo{}", withholdOrder.getBatchRequestNo());
                        }
                    }else {
                        log.info("withholdOrder为null");
                    }
                }
            }
        }catch (Exception e){
            log.error("handBatchOrderFailWithhold fail ",e);
        }
    }

    public boolean handForWithhold(BatchTransOrder batchOrder,WithholdOrder withholdOrder) throws ExecutionException, InterruptedException {
        DateTime endTime = new DateTime(new Date()).plusMinutes(-15);

        if (withholdOrder != null && withholdOrder.getUpdateTime().getTime() > endTime.getMillis()){
            log.info("代扣订单更新时间没有达到15分钟，不处理,batchRequestNo={}",batchOrder.getBatchRequestNo());
            return false;
        }
        //处理中，同步代扣状态
        if (withholdOrder!=null && 1 == withholdOrder.getStatus()){
            log.info("标的代扣任务正在进行中,标的号={}，批次号={}",batchOrder.getProjectId(),batchOrder.getBatchRequestNo());
            QueryTransactionRequest requestRecharge = new QueryTransactionRequest();
            requestRecharge.setRequestNo(withholdOrder.getRequestNo());
            requestRecharge.setPlatformUserNo(lanMaoProperties.getPlatformNo());
            CompletableFuture<QueryRechargeResponse> responseCompletableFuture =  lanMaoDirectService.queryRecharge(requestRecharge);
            QueryRechargeResponse rechargeResponse = responseCompletableFuture.get();
            log.info("还款流程补单，查询代扣状态,代扣订单号requestNo={}响应结果response={}",withholdOrder.getRequestNo(),JSON.toJSONString(rechargeResponse));

            /**
             * [{"code":1,"errorCode":"100007","errorMessage":"该交易不存在! ","status":"INIT","success":false}]
             */
            if (rechargeResponse == null){
                log.info("查询状态结果为空，无响应 requestNo{}",withholdOrder.getRequestNo());
                return false;
            }
            else if ("100007".equals(rechargeResponse.getErrorCode())){
                Date createTime = withholdOrder.getCreateTime();
                //如果是30分钟以内
                if (new DateTime(createTime).plusMinutes(30).getMillis() > new Date().getTime()){
                    AccountBase accountBase = accountBaseMapperExt.selectByPrimaryKey(withholdOrder.getAccountId());
                    if (accountBase == null){
                        log.info("账户不存在,accountId={}",withholdOrder.getAccountId());
                        return false;
                    }
                    log.info("交易不存在，30min内重新发起 requestNo{}",withholdOrder.getRequestNo());
                    PayCompanyEnum payCompanyEnum = PayCompanyEnum.enumOf(withholdOrder.getPayChannelCode());
                    WithholdOrder withholdOrderUpdate = new WithholdOrder();
                    withholdOrderUpdate.setId(withholdOrder.getId());
                    withholdOrderUpdate.setUpdateTime(new Date());
                    withholdOrderMapperExt.updateByPrimaryKeySelective(withholdOrderUpdate);
                    lanmaoRefundLocalService.directRecharge(accountBase.getAccountNo(),withholdOrder.getRequestNo(),withholdOrder.getAmount(),payCompanyEnum);
                }else {
                    WithholdOrder withholdOrderNew = withholdOrderMapperExt.selectByPrimaryKey(withholdOrder.getId());
                    //最进5分钟有更新过
                    if(withholdOrderNew.getUpdateTime().getTime()+1000*60*5 > new Date().getTime()){
                        log.info("5分钟内有update,requestNo={}",withholdOrder.getRequestNo());
                        return false;
                    }
                    //当两个JOB同时进入时，一个走30min内，一个走超过30min，会导致冲突
                    log.info("交易不存在，代扣失败 requestNo{}",withholdOrder.getRequestNo());
                    refundBaseLocalService.withHoldFailRollBackStatus(batchOrder.getBatchRequestNo(), withholdOrder.getId(), batchOrder.getId());
                }
                return false;
            }
            //业务处理失败且非系统异常,更新成失败
            else if (ResponseStatusEnum.INIT.getValue().equals(rechargeResponse.getStatus())&& !"100001".equals(rechargeResponse.getErrorCode())){
                log.info("调用成功，代扣订单(还款)状态处理失败,requestNo={},不处理",withholdOrder.getRequestNo());
                //refundBaseLocalService.withHoldFailRollBackStatus(batchOrder.getBatchRequestNo(),batchOrder.getWithholdOrderId(),batchOrder.getId());
                return false;
            }

            // 调用成功且充值成功，更新订单状态为成功,但是还款订单会失败
            else if(isRechargeSuccess(rechargeResponse)){
                AccountBatchTransOrderDTO dto = new AccountBatchTransOrderDTO();
                dto.setWithholdRequestNo(withholdOrder.getRequestNo());
                dto.setBorrowerUserId(batchOrder.getBorrowerUserId());
                dto.setBatchTransOrderId(batchOrder.getId());
                log.info("代扣流程补单成功，requestNo={}",withholdOrder.getRequestNo());
                int count = refundBaseLocalService.updateWithHoldOrderStatusAndAccountAmount(withholdOrder.getAccountId(), withholdOrder.getId(), withholdOrder.getAmount(), OrderEndTypeEnum.FAIL, dto);
                //refundBaseLocalService.updateBatchTransOrderStatus(batchOrder.getBatchRequestNo(),batchOrder.getId(),RefundStatusEnum.FAIL);
                batchOrder.setWithholdOrderId(withholdOrder.getId());
                log.info("更新代扣订单和记账成功,处理数据{}",count);
                return count==1;
            }
            //支付失败
            else if(isRechargeFailed(rechargeResponse)){
                log.info("批次号{},支付失败，处理成失败,{}",withholdOrder.getBatchRequestNo(),JSON.toJSONString(rechargeResponse));
                refundBaseLocalService.withHoldFailRollBackStatus(batchOrder.getBatchRequestNo(),withholdOrder.getId(),batchOrder.getId());
                return false;
            }else {
                log.info("批次号{},代扣状态未知，不处理,{}",withholdOrder.getBatchRequestNo(),JSON.toJSONString(rechargeResponse));
                return false;
            }
        }
        //代扣失败，还款失败
        else if(withholdOrder!=null && 3 == withholdOrder.getStatus()){
            log.info("代扣失败，还款失败,batchRequestNo={}",batchOrder.getBatchRequestNo());
            refundBaseLocalService.withHoldFailRollBackStatus(batchOrder.getBatchRequestNo(),withholdOrder.getId(),batchOrder.getId());
            return false;
        }
        //代扣成功
        else if (withholdOrder != null && 2 == withholdOrder.getStatus()){
            log.info("代扣成功，处理继续补单,batchRequestNo={}",batchOrder.getBatchRequestNo());
            batchOrder.setWithholdOrderId(withholdOrder.getId());
            return true;
        }
        else {
            //代扣订单为空
            log.info("代扣订单为空,batchRequestNo={}",batchOrder.getBatchRequestNo());
            return true;
        }
    }
    public boolean isRechargeSuccess(QueryRechargeResponse rechargeResponse){
        Assert.notNull(rechargeResponse,"参数不合法");
        return  ResponseCodeEnum.SUCCESS.getValue().equals(rechargeResponse.getCode())
                && ResponseStatusEnum.SUCCESS.getValue().equals(rechargeResponse.getStatus())
                && rechargeResponse.getRecords()!=null
                && rechargeResponse.getRecords().size()>0
                && RechargeStatusEnum.SUCCESS.name().equals(rechargeResponse.getRecords().get(0).getStatus());
    }

    public boolean isRechargeFailed(QueryRechargeResponse rechargeResponse){
        Assert.notNull(rechargeResponse,"参数不合法");
        return ResponseCodeEnum.SUCCESS.getValue().equals(rechargeResponse.getCode())
                && ResponseStatusEnum.SUCCESS.getValue().equals(rechargeResponse.getStatus())
                && rechargeResponse.getRecords()!=null
                && rechargeResponse.getRecords().size()>0
                && RechargeStatusEnum.FAIL.name().equals(rechargeResponse.getRecords().get(0).getStatus());
    }

    /**
     * 是否发生过代扣 false表示未发生代扣，true表是有代扣
     * @param batchOrder
     * @return
     */
    private boolean isWithholdExist(BatchTransOrder batchOrder){
        if (batchOrder != null && batchOrder.getWithholdOrderId()!=null && batchOrder.getWithholdOrderId()!=0){
            return true;
        }
        return false;
    }

    /**
     * 预处理订单同步
     * @param batchOrder
     */
//    private boolean handPreTransactionStatus(BatchTransOrder batchOrder) throws ExecutionException, InterruptedException {
//        DateTime endTimeDate = new DateTime(new Date()).plusMinutes(-15);
//
//        if (!HintManagerHolder.isMasterRouteOnly()) {
//            HintManagerHolder.clear();
//            HintManager hintManager = HintManager.getInstance();
//            hintManager.setMasterRouteOnly();
//        }
//        ProTransactionOrder proTransactionOrder = proTransactionOrderMapperExt.queryProTransactionOrderNotDelByBatchRequestNo(batchOrder.getBatchRequestNo());
//
//        if (proTransactionOrder != null && proTransactionOrder.getUpdateTime().getTime() > endTimeDate.getMillis()){
//            log.info("预处理订单，处理时间没有达到15分钟，不处理,batchRequestNo={}",batchOrder.getBatchRequestNo());
//            return false;
//        }
//        //预处理订单不存在
//        if (proTransactionOrder == null){
//            //refundBaseLocalService.updateBatchTransOrderStatus(batchOrder.getBatchRequestNo(),batchOrder.getId(),RefundStatusEnum.FAIL);
//
//            if (TransactionTypeEnum.REPAYMENT.getValue().equals(batchOrder.getTradeType()) && !isWithholdExist(batchOrder)){
//                log.info("批量未进行还款预处理，数据为空，暂不处理,batchRequestNO = {}",batchOrder.getBatchRequestNo());
//                refundBaseLocalService.updateBatchTransOrderStatus(batchOrder.getBatchRequestNo(),batchOrder.getId(),RefundStatusEnum.FAIL);
//                return false;
//            }else if (TransactionTypeEnum.COMPENSATORY.getValue().equals(batchOrder.getTradeType())){
//                log.info("垫付订单更新直接更新为失败");
//                refundBaseLocalService.updateBatchTransOrderStatus(batchOrder.getBatchRequestNo(),batchOrder.getId(),RefundStatusEnum.FAIL);
//            }else{
//                log.info("有代扣成功，但是没有生成预处理订单,batchRequestNO = {},batchOrder.getBatchRequestNo()");
//                AccountBatchTransOrderDTO dto = this.buildTradeDTO(batchOrder,null);
//                AccountBase accountBase = refundQueryLocalService.getAccountBase(dto);
//                Assert.notNull(accountBase,"存管账户(借款账户)没有开通,user_id="+dto.getBorrowerUserId());
//                if ((dto.getRepayStatus() == RepayStatusEnum.BADLOANS.getCode() || dto.getRepayStatus() == RepayStatusEnum.OVERDUE.getCode())
//                        && !dto.getBatchRefundType().equals(BatchRefundTypeEnum.NEED_GUARANTEE_REFUND.getValue())) {
//                    if (accountBase.getAvailableAmount().compareTo(BigDecimal.ZERO)==0){
//                        refundBaseLocalService.updateBatchTransOrderStatus(dto.getBatchRequestNo(), dto.getBatchTransOrderId(), RefundStatusEnum.FAIL);
//                        return false;
//                    }
//                    else if (accountBase.getAvailableAmount().compareTo(batchOrder.getAmount())>=0){
//                        BigDecimal canRefundAmount = batchOrder.getAmount();
//                        dto.setAmount(canRefundAmount);
//                    }
//                }
//                accountRefundHandleLocalService.amountEnough(dto,accountBase.getId(),accountBase.getAccountNo(),batchOrder.getId());
//                return true;
//            }
//            return false;
//        }
//        //如果没有发生代扣，直接处理还款订单为失败
//        else if (proTransactionOrder.getStatus() == RefundStatusEnum.HANDLING.getValue()){
//            log.info("预处理订单正在处理中,发起同步预处理状态流程,batchRequestNo={}",batchOrder.getBatchRequestNo());
//            QueryTransactionRequest requestRecharge = new QueryTransactionRequest();
//            requestRecharge.setRequestNo(proTransactionOrder.getRequestNo());
//            requestRecharge.setPlatformUserNo(lanMaoProperties.getPlatformNo());
//            CompletableFuture<QueryPretransactionResponse> responseCompletableFuture =  lanMaoDirectService.queryPretransaction(requestRecharge);
//            QueryPretransactionResponse response = responseCompletableFuture.get();
//            log.info("预处理订单{}状态查询响应:{}",proTransactionOrder.getRequestNo(), JSON.toJSONString(response));
//            if (response == null ){
//                log.info("预处理响应为空,batchRequestNO={}",batchOrder.getBatchRequestNo());
//                return false;
//            }
//            //交易不存在
//           //{"code":1,"errorCode":"100007","errorMessage":"该交易不存在! ","status":"INIT","success":false}
//            if (ResponseCodeEnum.FAILURE.getValue().equals(response.getCode())
//                    && "INIT".equals(response.getStatus())
//                    && "100007".equals(response.getErrorCode())){
//                log.info("预处理订单号{}不存在,返回对应",proTransactionOrder.getRequestNo(), JSON.toJSONString(response));
//                refundBaseLocalService.freezePreTransactionFailRollBackStatus(proTransactionOrder.getId(),batchOrder.getId(),batchOrder.getBatchRequestNo());
//            }
//            //预处理失败且非系统异常,更新成失败
//            else if (response.getRecords()!=null
//                    && response.getRecords().size()>0
//                    && "FAIL".equals(response.getRecords().get(0).getStatus())){
//                log.info("调用成功，还款预处理订单(还款)状态处理失败,batchRequestNo={}",batchOrder.getBatchRequestNo());
//                refundBaseLocalService.freezePreTransactionFailRollBackStatus(proTransactionOrder.getId(),batchOrder.getId(),batchOrder.getBatchRequestNo());
//                return false;
//            }
//            // 调用成功且预处理成功，更新订单状态为成功
//            /**
//             * {"code":0,"records":[{"bizType":"REPAYMENT","createTime":"20180307154238","freezeAmount":207.06,"platformUserNo":"53960601218588673","status":"UNFREEZED","transactionTime":"20180307154243","unfreezeAmount":207.06}],"status":"SUCCESS","success":true}
//             */
//            else if(response.getRecords()!=null
//                    && response.getRecords().size()>0
//                    && "FREEZED".equals(response.getRecords().get(0).getStatus())){
//                log.info("预处理查询结果为空，更新本地状态，并进行还款补单,batchRequestNO={}",batchOrder.getBatchRequestNo());
//                AccountBatchTransOrderDTO dto = this.buildTradeDTO(batchOrder,proTransactionOrder);
//
//                int count = refundBaseLocalService.updateProTransactionOrderStatusAndAccountAmount(proTransactionOrder.getId(),proTransactionOrder.getAccountId(),proTransactionOrder.getAmount(),dto);
//                log.info("更新预处理订单和记账成功,处理数据{}",count);
//                if (count == 1) {
//                    //还款逻辑
//                    accountRefundHandleLocalService.refund(dto, batchOrder.getId());
//                }
//                return true;
//            }else {
//                log.info("批次号{},预处理状态未知，不处理,{}",proTransactionOrder.getBatchRequestNo(),JSON.toJSONString(proTransactionOrder));
//                return false;
//            }
//        }
//        return false;
//
//    }

    private AccountBatchTransOrderDTO buildTradeDTO(BatchTransOrder batchOrder,ProTransactionOrder proTransactionOrder){
        AccountBatchTransOrderDTO dto = new AccountBatchTransOrderDTO();
        //dto.setWithholdRequestNo(withholdOrder.getRequestNo());
        dto.setBorrowerUserId(batchOrder.getBorrowerUserId());
        dto.setBatchTransOrderId(batchOrder.getId());
        dto.setTradeType(batchOrder.getTradeType());
        dto.setGuaranteeUserId(this.getGuaranteeUserId());
        dto.setProjectId(batchOrder.getProjectId());
        dto.setRepayStatus(batchOrder.getRepayStatus());
        dto.setCurrentPeriod(batchOrder.getCurrentPeriod());
        dto.setTotalPeriod(batchOrder.getTotalPeriod());
        dto.setBatchRefundType(batchOrder.getBatchRefundType());
        dto.setBatchRequestNo(batchOrder.getBatchRequestNo());
        dto.setAmount(batchOrder.getAmount());
        dto.setProjectTitle(batchOrder.getProjectTitle());
        if (proTransactionOrder != null){
            dto.setProTransOrderId(proTransactionOrder.getId());
            dto.setFreezeRequestNo(proTransactionOrder.getRequestNo());
            dto.setAmount(proTransactionOrder.getAmount());
        }
        if(batchOrder.getBatchRefundType().equals(BatchRefundTypeEnum.OVER_DEBT.getValue())){
            dto.setIsOverDebt(true);
        }
        return dto;
    }


    /**
     * 预处理回滚
     * @return
     */
    public boolean rollbackProTransaction(Long proTransactionOrderId){
        log.info("rollbackProTransaction-proTransactionOrderId={}",proTransactionOrderId);
        ProTransactionOrder proTransactionOrder = proTransactionOrderMapperExt.selectByPrimaryKey(proTransactionOrderId);
        Assert.notNull(proTransactionOrder,"预处理订单不存在");
        BatchTransOrder batchOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(proTransactionOrder.getBatchRequestNo());
        Assert.notNull(batchOrder,"还款订单不存在");
        //原状态为成功
        if (2 == proTransactionOrder.getStatus() && proTransactionOrder.getDelFlag()==0) {
            LanMaoResponse lanMaoResponse = lanmaoRefundLocalService.cancelProTransaction(proTransactionOrder);
            if (lanMaoResponse!=null
                    && ResponseCodeEnum.SUCCESS.getValue().equals(lanMaoResponse.getCode())
                    && ResponseStatusEnum.SUCCESS.getValue().equals(lanMaoResponse.getStatus())){

                AccountBatchTransOrderDTO dto = new AccountBatchTransOrderDTO();
                dto.setProTransOrderId(proTransactionOrder.getId());
                dto.setBorrowerUserId(batchOrder.getBorrowerUserId());
                dto.setTradeType(batchOrder.getTradeType());
                dto.setGuaranteeUserId(this.getGuaranteeUserId());
                ((AccountRefundProcessAutoLocalService)AopContext.currentProxy()).rollbackForBatchOrder(proTransactionOrder,batchOrder,dto);
                return true;
            }
        }

        return false;
    }
    @Transactional
    public void rollbackForBatchOrder(ProTransactionOrder proTransactionOrder,BatchTransOrder batchOrder,AccountBatchTransOrderDTO dto){
        int count = refundBaseLocalService.rollbackProTransactionOrderStatusAndAccountAmount(proTransactionOrder.getId(),proTransactionOrder.getAccountId(),proTransactionOrder.getAmount(),dto);
        log.info("回滚数据量count={}",count);
        if (count==1){
            //还款订单更新成功失败
            refundBaseLocalService.updateBatchTransOrderStatus(batchOrder.getBatchRequestNo(),batchOrder.getId(),RefundStatusEnum.FAIL);
        }
    }

    /**
     * 代扣结果异步通知处理
     * 返回null时，不作应答会重复通知
     */
//    public UpdateRechargeResponseDTO callbackForWithhold(UpdateRechargeRequestDTO responseDTO){
//        log.info("代扣结果通知dto={}",JSON.toJSONString(responseDTO));
//
//        if (responseDTO == null || ResponseStatusEnum.INIT.getValue().equals(responseDTO.getResponseCodeEnum())){
//            log.info("查询代扣状态失败，无响应");
//            return null;
//        }
//        WithholdOrder withholdOrder = withholdOrderMapperExt.selectOrderByRequestNo(responseDTO.getRequestNo());
//
//        if (withholdOrder == null){
//            log.info("无效代扣订单号,requestNo={}",responseDTO.getRequestNo());
//            return new UpdateRechargeResponseDTO();
//        }
//        //列表查询锁定查询范围，每一个订单都重新查询一次，拿到最新订单状态再作处理
//        if (!HintManagerHolder.isMasterRouteOnly()) {
//            HintManagerHolder.clear();
//            HintManager hintManager = HintManager.getInstance();
//            hintManager.setMasterRouteOnly();
//        }
//        BatchTransOrder batchOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(withholdOrder.getBatchRequestNo());
//        if (batchOrder == null){
//            log.info("还款订单不存在,BatchRequestNo={}",withholdOrder.getBatchRequestNo());
//        }
//        //业务处理失败且非系统异常,更新成失败
//        else if (RechargeStatusEnum.FAIL.name().equals(responseDTO.getRechargeStatusEnum()) && !"100001".equals(responseDTO.getErrorCode())){
//            log.info("调用成功，代扣订单(还款)状态处理失败,requestNo={}",batchOrder.getBatchRequestNo());
//            refundBaseLocalService.withHoldFailRollBackStatus(batchOrder.getBatchRequestNo(),withholdOrder.getId(),batchOrder.getId());
//        }
//
//        // 调用成功且充值成功，更新订单状态为成功,但是还款订单会失败
//        else if("0".equals(responseDTO.getResponseCodeEnum())
//                && RechargeStatusEnum.SUCCESS.name().equals(responseDTO.getRechargeStatusEnum())){
//            AccountBatchTransOrderDTO dto = new AccountBatchTransOrderDTO();
//            dto.setWithholdRequestNo(withholdOrder.getRequestNo());
//            dto.setBorrowerUserId(batchOrder.getBorrowerUserId());
//            dto.setBatchTransOrderId(batchOrder.getId());
//            int count = refundBaseLocalService.updateWithHoldOrderStatusAndAccountAmount(withholdOrder.getAccountId(), withholdOrder.getId(), withholdOrder.getAmount(), OrderEndTypeEnum.FAIL, dto);
//            //refundBaseLocalService.updateBatchTransOrderStatus(batchOrder.getBatchRequestNo(),batchOrder.getId(),RefundStatusEnum.FAIL);
//            batchOrder.setWithholdOrderId(withholdOrder.getId());
//            log.info("更新代扣订单和记账成功,处理数据{}",count);
//            if (count == 1){
//                try {
//                    this.handPreTransactionStatus(batchOrder);
//                } catch (ExecutionException | InterruptedException e) {
//                    log.error("handPreTransactionStatus-error-");
//                    e.printStackTrace();
//                }
//            }
//        }else if("0".equals(responseDTO.getResponseCodeEnum())
//                && RechargeStatusEnum.PENDDING.name().equals(responseDTO.getRechargeStatusEnum())){
//            log.info("批次号{},状态正在支付中，不处理,{}",withholdOrder.getBatchRequestNo(),JSON.toJSONString(responseDTO));
//            return null;
//        }else {
//            log.info("批次号{},状态未知，不处理,{}",withholdOrder.getBatchRequestNo(),JSON.toJSONString(responseDTO));
//            return null;
//        }
//
//        UpdateRechargeResponseDTO updateRechargeResponseDTO = new UpdateRechargeResponseDTO();
//        updateRechargeResponseDTO.setRequestNo(responseDTO.getRequestNo());
//        updateRechargeResponseDTO.setOrderId(withholdOrder.getId());
//        updateRechargeResponseDTO.setAmount(responseDTO.getAmount());
//        updateRechargeResponseDTO.setStatus(withholdOrder.getStatus());
//        updateRechargeResponseDTO.setUserId(withholdOrder.getUserId());
//        updateRechargeResponseDTO.setChannelErrorMessage(responseDTO.getChannelErrorMessage());
//        updateRechargeResponseDTO.setErrorMessage(responseDTO.getErrorMessage());
//        log.info("充值处理完毕，返回前端{}", JSONObject.toJSONString(updateRechargeResponseDTO));
//        return updateRechargeResponseDTO;
//    }

    /**
     * 代扣补单
     * @param withholdOrderId
     * @param endType
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public void complementWithhold(Long withholdOrderId, RefundStatusEnum status, OrderEndTypeEnum endType) {
        //查询代扣订单
        WithholdOrder withholdOrder = withholdOrderMapperExt.selectByPrimaryKey(withholdOrderId);
        if (withholdOrder == null) {
            log.error("代扣订单不存在");
            throw new BizException("ACC10010");
        }
        //查询还款订单
        BatchTransOrder batchTransOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(withholdOrder.getBatchRequestNo());
        if (batchTransOrder == null) {
            log.error("还款订单不存在");
            throw new BizException("ACC10011");
        }
        this.complementWithhold(withholdOrder, batchTransOrder, status, endType);
    }

    private void complementWithhold(WithholdOrder withholdOrder, BatchTransOrder batchTransOrder, RefundStatusEnum status, OrderEndTypeEnum endType) {
        if (status == RefundStatusEnum.FAIL) {
            //发送消息
            log.info("complementWithhold.cardWithholdFailMsgSend start");
            refundMsgLocalService.cardWithholdFailMsgSend(batchTransOrder);
            log.info("complementWithhold.cardWithholdFailMsgSend end");
            accountRefundHandleLocalService.withholdFail(withholdOrder.getId(), batchTransOrder.getId(), batchTransOrder.getProjectId(), batchTransOrder.getCurrentPeriod(), batchTransOrder.getBatchRequestNo());
            return;
        }
        if (status == RefundStatusEnum.SUCCESS) {
            this.withholdSucceed(withholdOrder, batchTransOrder, endType);
        }
    }

    private void withholdSucceed(WithholdOrder withholdOrder, BatchTransOrder batchTransOrder, OrderEndTypeEnum endType) {
        RLock lock = redissonClient.getLock(new StringBuffer().append(RedissonLockConstant.REFUND_TRADE_TYPE).append(TransactionTypeEnum.REPAYMENT.name()).append(RedissonLockConstant.REFUND_ACCOUNT).append(withholdOrder.getUserId()).toString());
        try {
            lock.lock();
            //查询用户帐户
            AccountBase account = accountBaseMapperExt.selectByPrimaryKey(withholdOrder.getAccountId());
            if (account == null) {
                log.error("借款人账户不存在");
                throw new BizException("ACC10004");
            }
            AccountBatchTransOrderDTO dto = new AccountBatchTransOrderDTO();
            dto.setBorrowerUserId(withholdOrder.getUserId());
            dto.setBatchRequestNo(withholdOrder.getBatchRequestNo());
            dto.setWithholdRequestNo(withholdOrder.getRequestNo());
            dto.setTradeType(TransactionTypeEnum.REPAYMENT.getValue());
            dto.setBatchRefundType(batchTransOrder.getBatchRefundType());
            dto.setProjectId(batchTransOrder.getProjectId());
            dto.setAmount(batchTransOrder.getAmount());
            dto.setCurrentPeriod(batchTransOrder.getCurrentPeriod());
            dto.setTotalPeriod(batchTransOrder.getTotalPeriod());
            dto.setProjectTitle(batchTransOrder.getProjectTitle());
            dto.setRepayStatus(batchTransOrder.getRepayStatus());
            dto.setBatchTransOrderId(batchTransOrder.getId());
            //更新账户余额和代扣订单状态
            int count = refundBaseLocalService.updateWithHoldOrderStatusAndAccountAmount(account.getId(), withholdOrder.getId(), withholdOrder.getAmount(), endType, dto);

            if (count == 1) {
                //余额充足流程
                accountRefundHandleLocalService.amountEnough(dto, account.getId(), account.getAccountNo(), batchTransOrder.getId());
            }
        } finally {
            lock.unlock();
        }
    }
}
